package pl.put.dcs.workManagerServer.projectManager.queueManager;

import org.apache.log4j.Logger;
import pl.put.dcs.workManagerServer.config.ProjectConfigManager;
import pl.put.dcs.workManagerServer.projectManager.queueManager.cacheManeger.Cache;
import pl.put.dcs.workManagerServer.projectManager.queueManager.cacheManeger.CacheManagerImpl.CacheManagerImpl;
import pl.put.dcs.workManagerServer.projectManager.queueManager.cacheManeger.CacheManagerImpl.jbossCacheManager.JBossCacheManager;
import pl.put.dcs.workManagerServer.projectManager.queueManager.cacheManeger.listeners.CacheContentChangeListener;
import pl.put.dcs.workManagerServer.projectManager.queueManager.listeners.QueueStatusListener;
import pl.put.dcs.workManagerServer.projectManager.queueManager.taskWatchdog.TaskWatchdog;
import pl.put.dcs.workManagerServer.projectManager.queueManager.taskWatchdog.listeners.PacketStatusListener;
import pl.put.dcs.workManagerServer.serviceConnectors.ControlModuleServerConnector;
import pl.put.dcs.workManagerServer.serviceConnectors.ControlModuleServerConnectorInterface;
import pl.put.model.packet.Packet;
import pl.put.model.project.Project;

/**
 *  Zak&#322;adamy, ze kazdy projekt moze miec tylko jedna kolejke, ktorej
 *        odzwierciedleniem jest QueueManager.
 */
// <editor-fold defaultstate="collapsed" desc=" UML Marker ">
// #[regen=yes,id=DCE.B68CDC19-960B-0066-07FD-172DA8799391]
// </editor-fold>
public class QueueManager
{

    public static Logger log = Logger.getLogger( QueueManager.class.getName() );

    private QueueStatusListener queueStatusListener;

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,id=DCE.BFDA851B-C985-39A3-B079-41E42194311D]
    // </editor-fold>
    private TaskWatchdog taskWatchdog;

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,id=DCE.25A32712-B3D5-F1CF-90E5-76A2E7377B4F]
    // </editor-fold>
    private CacheManagerImpl cacheManager;
    private CacheManagerImpl tmpCache;
    private Project project;
    private ProjectConfigManager projectConfigManager;
    private ControlModuleServerConnectorInterface controlModuleServerConnector;
    private int minPacketsInCache;

    public QueueManager( Project project )
    {
        // generowanie takiego fakeowego listenera, zeby pozniej nic sie nie burzylo o to, ze jest nullem
        queueStatusListener = new QueueStatusListener()
        {
            public void packetsNumberUnderMin( int number )
            {
               
            }
        };
        this.project = project;
        projectConfigManager = new ProjectConfigManager( project );
        this.minPacketsInCache = projectConfigManager.getMinPacketsInChache();
        Cache cacheProp = new Cache();
        tmpCache = new JBossCacheManager( cacheProp, "pl/put/workManagerServer/resources/jbosscacheTmpSpace.xml" );
        cacheManager = new JBossCacheManager( cacheProp, "pl/put/workManagerServer/resources/jbosscacheConfig.xml" );
        cacheManager.setCacheContentChangeListener( new CacheContentChangeListener()
        {

            public void cacheContentChanged( Packet packet, ACTION action )
            {
                if ( action == ACTION.DETACHED )
                {
                    putPacketInTmpSpace( packet );

                }
            }
        } );

        // ustawienie watchDoga zadan
        TaskWatchdog twd = new TaskWatchdog( tmpCache );
        // listener sluzacy do komunikacji z managerem kolejek
        twd.setPacketStatusListener( new PacketStatusListener()
        {

            public void packetStatusChanged( Packet packet, STATUS status )
            {
                if ( status == STATUS.TERMINATED )
                {
                    putPacketInPublicSpace( packet );
                }
            }
        } );
        setTaskWatchdog( twd );
        // uruchamia watek watchdog-a
        getTaskWatchdog().start();
        // namiar na obiekt informacyjny
        controlModuleServerConnector = ControlModuleServerConnector.getInstance();


    }

    /**
     * Umieszczeni pakietu w przstrzeni publicznej
     * @param packet
     */
    public void putPacketInPublicSpace( Packet packet )
    {
        // musimy sprawdzic, czy
        // metoda wywolana zaraz po zdjeciu packeta z kolejki, wiec nie musimy sie martwic zeby z niej pozbyc sie tego elementu
        putTaskInQueue( packet );
        controlModuleServerConnector.setPacketStatusWaited( packet );
    }


    /**
     * Wrzuca packet do templorarnej przestrzeni. Jezeli zostanie pobrany pakiet z przestrzeni publicznej, to trafia
     * on na pewien czas to temp. Po tym czasie, jezeli nie zostanie on usuniety z tmp, nastepuje ponowne przywrocenie do do przestrzeni publicznej.
     * @param packet
     */
    private void putPacketInTmpSpace( Packet packet )
    {
        tmpCache.putPacketInCache( packet );
        controlModuleServerConnector.setPacketStatusStarted( packet );
        // jezeli ilosc packetow w przestrzeni glownej jest mniejsza niz okreslone minimum, to zostaje wygenerowane zdarzenie
        int number = controlModuleServerConnector.countActiveTasks( project );
        if ( minPacketsInCache > number )
        {
            queueStatusListener.packetsNumberUnderMin( number );
        }
    }


    public QueueStatusListener getQueueStatusListener()
    {
        return queueStatusListener;
    }

    public void setQueueStatusListener( QueueStatusListener queueStatusListener )
    {
        this.queueStatusListener = queueStatusListener;
    }


    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,regenBody=yes,id=DCE.6564BC53-3F05-2416-0154-671C5EDFC38D]
    // </editor-fold>
    public TaskWatchdog getTaskWatchdog()
    {
        return taskWatchdog;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,regenBody=yes,id=DCE.B79F7251-A77E-D3C1-2292-364CB90779C1]
    // </editor-fold>
    public void setTaskWatchdog( TaskWatchdog val )
    {
        this.taskWatchdog = val;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,id=DCE.45033950-C5AC-DFDD-3C49-3B100567B074]
    // </editor-fold>
    public void putTaskInQueue( Packet packet )
    {
        cacheManager.putPacketInCache( packet );

    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,id=DCE.4BBC719C-3FE5-2D6C-C467-45106974CC45]
    // </editor-fold>
    public Packet getPacketFromQueueById( String id )
    {
        return cacheManager.getPacketFromCache( id );
    }

    public Packet popPacketFromQueueById( String id )
    {
        return cacheManager.popPacketFromCache( id );
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,regenBody=yes,id=DCE.7B4B26CF-F104-7F36-1FC8-B0299E6CCFBD]
    // </editor-fold>
    public CacheManagerImpl getCacheManager()
    {
        return cacheManager;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker ">
    // #[regen=yes,regenBody=yes,id=DCE.56863902-BAB8-6A7B-F9F0-04E4DA813F5E]
    // </editor-fold>
    public void setCacheManager( CacheManagerImpl val )
    {
        this.cacheManager = val;
    }
}

